import csv
import datetime
import math
import os
import shutil

from PyQt5 import QtCore, QtGui
from PyQt5.QtCore import QDate
from PyQt5.QtGui import QPixmap
from PyQt5.QtWidgets import QFileDialog, QMessageBox, QTableWidgetItem, QComboBox

from database import usedb
from projectinfo.pile import Ui_pile_MainWindow


class pile_window(Ui_pile_MainWindow):
    def __init__(self):
        super(pile_window, self).__init__()
        # 只显示关闭按钮
        self.setWindowFlags(QtCore.Qt.WindowCloseButtonHint)
        self.setupUi(self)
        self.init()
        self.show()

        # 信号和槽
        self.ledit_pile.textChanged.connect(self.pilepath_to_pilepic)
        self.ledit_pile.textChanged.connect(self.ledit_pile_changed)
        self.cbox_mile.editTextChanged.connect(self.cbox_mile_changed)
        self.dateed_begin.dateChanged.connect(self.date_changed)
        self.dateed_test.dateChanged.connect(self.date_changed)
        self.dsbox_test.textChanged.connect(self.set_layers_name)
        self.pbtn_picpath.clicked.connect(self.get_image_path)
        self.pbtn_check.clicked.connect(self.checkdata)
        self.pbtn_OK.clicked.connect(self.insert_pile_info)
        self.pbtn_quit.clicked.connect(self.close)

    def init(self):
        # 窗口初始化工作里程，掺灰量，施工日期，检测日期，施工桩长，检测桩长，芯样照片位置指定为dir_images
        # 设置桩号单行文本框输入内容为字母数字短划线
        from PyQt5.QtCore import QRegExp
        self.ledit_pile.setValidator(QtGui.QRegExpValidator(QRegExp("[a-zA-Z0-9--]+")))
        self.ledit_pile.setPlaceholderText("字母数字短划线")
        # 设置桩号单行文本框输入内容为字母数字短划线
        self.dir_proj = os.path.join(usedb.cur_path, usedb.cur_proj)
        self.csv_projinfo = os.path.join(self.dir_proj, f'{usedb.cur_proj}综合质量评分（表一）.csv')
        self.csv_piletotal = os.path.join(self.dir_proj, f'{usedb.cur_proj}汇总信息表（表二）.csv')
        self.csv_pile = os.path.join(self.dir_proj, f'{usedb.cur_proj}试验成果及得分表（表三）.csv')
        self.dir_images = os.path.join(self.dir_proj, 'images')
        self.ledit_picpath.setText(self.dir_images)
        self.num = 0
        if os.path.exists(self.csv_piletotal) and usedb.cur_proj!='':
            with open(self.csv_piletotal, 'r', newline='',encoding='utf-8') as csvfile:
                csvoutput = csv.reader(csvfile)
                pilehead_full = next(csvoutput)
                # 里程，掺灰量，施工日期，检测日期，施工桩长，实测桩长等
                miles, cements, datebegins, datetests, pilebegins, piletests = [], [], [], [], [], []
                for row in csvoutput:
                    self.num += 1
                    mile = row[2]
                    cement = row[3]
                    datebegin = row[4]
                    datetest = row[5]
                    pilebegin = row[7]
                    piletest = row[8]
                    miles.append(mile)
                    cements.append(cement)
                    datebegins.append(datebegin)
                    datetests.append(datetest)
                    pilebegins.append(pilebegin)
                    piletests.append(piletest)
                csvfile.close()
                # 根据检测桩长，设定表头，设定表格行数和列数
                pilehead_part = ['桩号', '里程', '龄期', '深度(m)', '硬度状态', '标贯击数', '杆长', '强度(MPa)']
                self.tbw_pile.setHorizontalHeaderLabels(pilehead_part)
                self.tbw_pile.setColumnCount(len(pilehead_part))
                pile_test_len = self.dsbox_test.value()
                layers = math.ceil(pile_test_len / 1.5)
                self.tbw_pile.setRowCount(layers)
                self.statusBar.showMessage(f'当前项目为{usedb.cur_proj}，项目路径为{self.dir_proj}')
                self.ledit_pile_changed()
                self.cbox_mile_changed()
                self.date_changed()
                self.set_layers_name()
            if miles != []:
                # 如果有桩，则根据汇总信息初始化窗口，否则pass
                self.cbox_mile.addItems(set(miles))
                self.cbox_cement.addItems(set(cements))
                dateparts = datebegins[0].split('-')
                self.dateed_begin.setDate(QDate(int(dateparts[0]), int(dateparts[1]), int(dateparts[2])))
                dateparts = datetests[0].split('-')
                self.dateed_test.setDate(QDate(int(dateparts[0]), int(dateparts[1]), int(dateparts[2])))
                self.dsbox_begin.setValue(float(pilebegins[0]))
                self.dsbox_test.setValue(float(piletests[0]))
            else:
                pass
        else:
            QMessageBox.warning(None, 'no project', 'please choose a project', QMessageBox.Ok)

    def ledit_pile_changed(self):
        # 桩号文本框变化时执行
        # 判断该桩是否存在
        self.dir_proj = os.path.join(usedb.cur_path, usedb.cur_proj)
        self.csv_piletotal = os.path.join(self.dir_proj, f'{usedb.cur_proj}汇总信息表（表二）.csv')
        pilenum = self.ledit_pile.text()
        if os.path.exists(self.csv_piletotal):
            with open(self.csv_piletotal, 'r', newline='',encoding='utf-8') as csvfile:
                csvoutput = csv.reader(csvfile)
                pilehead_full = next(csvoutput)
                for row in csvoutput:
                    if pilenum == row[1]:
                        self.ledit_pile.setText('000-00')
                        QMessageBox.warning(None, '提示', f'已存在{pilenum}', QMessageBox.Ok)
                csvfile.close()
        pile_test_len = self.dsbox_test.value()
        layers = math.ceil(pile_test_len / 1.5)
        # 桩号
        self.tbw_pile.setSpan(0, 0, layers, 1)
        data_pile = QTableWidgetItem(self.ledit_pile.text())
        data_pile.setTextAlignment(QtCore.Qt.AlignCenter)
        self.tbw_pile.setItem(0, 0, data_pile)

    def cbox_mile_changed(self):
        # 里程文本框变化时执行
        pile_test_len = self.dsbox_test.value()
        layers = math.ceil(pile_test_len / 1.5)
        # 里程
        self.tbw_pile.setSpan(0, 1, layers, 1)
        data_mile = QTableWidgetItem(self.cbox_mile.currentText())
        data_mile.setTextAlignment(QtCore.Qt.AlignCenter)
        self.tbw_pile.setItem(0, 1, data_mile)

    def date_changed(self):
        # 两个日期控件改变时执行
        pile_test_len = self.dsbox_test.value()
        layers = math.ceil(pile_test_len / 1.5)
        self.tbw_pile.setSpan(0, 2, layers, 1)
        datedays = self.get_days_between(self.dateed_begin.text(), self.dateed_test.text())
        data_days = QTableWidgetItem(str(datedays))
        data_days.setTextAlignment(QtCore.Qt.AlignCenter)
        self.tbw_pile.setItem(0, 2, data_days)

    def get_days_between(self, begin, test):
        begindate = datetime.datetime.strptime(begin, "%Y-%m-%d")
        testdate = datetime.datetime.strptime(test, "%Y-%m-%d")
        if begindate <= testdate:
            begin_to_test = testdate - begindate
            return begin_to_test.days
        else:
            QMessageBox.warning(None, "warning", "检测日期早于施工日期，错误！", QMessageBox.Ok)
            return 0

    def set_layers_name(self):
        # 根据桩长重设表格行数和硬度状态
        pile_test_len = self.dsbox_test.value()
        layers = math.ceil(pile_test_len / 1.5)
        self.tbw_pile.setRowCount(layers)
        # 填写深度（m）
        for i in range(0, layers):
            combox = QComboBox()
            combox.addItems(
                ['坚硬', '坚硬-硬塑', '硬塑', '硬塑-可塑', '可塑', '可塑-软塑', '软塑', '软塑-流塑', '流塑'])
            self.tbw_pile.setCellWidget(i, 4, combox)
            if i < layers - 1:
                data_layer = QTableWidgetItem(f'{i * 1.5}m～{(i + 1) * 1.5}m')
                data_layer.setTextAlignment(QtCore.Qt.AlignCenter)
            else:
                data_layer = QTableWidgetItem(f'{i * 1.5}m～{pile_test_len}m')
                data_layer.setTextAlignment(QtCore.Qt.AlignCenter)
            self.tbw_pile.setItem(i, 3, data_layer)
        # 桩号、里程和龄期 需要重新合并单元格
        self.tbw_pile.setSpan(0, 0, layers, 1)
        self.tbw_pile.setSpan(0, 1, layers, 1)
        self.tbw_pile.setSpan(0, 2, layers, 1)

    def pilepath_to_pilepic(self):
        # 根据文件夹路径，自动加载图片。支持jpg和png两种格式图片
        pilepic_path = os.path.join(self.ledit_picpath.text(), self.ledit_pile.text())
        pilepic_path_jpg = pilepic_path + '.jpg'
        pilepic_path_png = pilepic_path + '.png'
        if os.path.exists(pilepic_path_jpg):
            self.lab_pilepic.setPixmap(
                QPixmap(pilepic_path_jpg).scaled(QtCore.QSize(510, 350), aspectRatioMode=QtCore.Qt.IgnoreAspectRatio))
        elif os.path.exists(pilepic_path_png):
            self.lab_pilepic.setPixmap(
                QPixmap(pilepic_path_png).scaled(QtCore.QSize(510, 350), aspectRatioMode=QtCore.Qt.IgnoreAspectRatio))
        else:
            pass

    def get_image_path(self):
        # 获得图片文件夹位置，显示在单行文本框
        if self.ledit_picpath.text() == '':
            path = QFileDialog.getExistingDirectory(None, "选择图片文件夹路径", os.getcwd(), QFileDialog.ShowDirsOnly)
        elif os.path.exists(self.ledit_picpath.text()):
            path = QFileDialog.getExistingDirectory(None, "选择图片文件夹路径", self.ledit_picpath.text(),
                                                    QFileDialog.ShowDirsOnly)
        if path != '':
            self.ledit_picpath.setText(path)
            self.pilepath_to_pilepic()
        else:
            QMessageBox.warning(None, '未找到文件夹', '请选择一个文件夹', QMessageBox.Ok)

    def checkdata(self):
        """"
        桩评分前对数据格式、数据合理性和图片是否存在进行检查。
        桩号、里程要有，击数和杆长必须为数字，mpa可以全为空，当前文本框显示路径下的图片要存在
        """""
        flag = True
        # 1、获取输入的桩号、里程，判断是否存在
        pile_test_len = self.dsbox_test.value()
        pilenum = self.ledit_pile.text()
        mile = self.cbox_mile.currentText()
        layers = math.ceil(pile_test_len / 1.5)

        if pilenum == '' or mile == '':
            QMessageBox.warning(None, "提示", '桩号或里程为空，请检查！', QMessageBox.Ok)
            flag = True
        for i in range(0, layers):
            if self.tbw_pile.item(i, 5) is None or self.tbw_pile.item(i, 6) is None or self.tbw_pile.item(i,
                                                                                                          5).text() == '' or self.tbw_pile.item(
                    i, 6).text() == '':
                # item为空，则得不到text，提示错误，并退出。
                QMessageBox.warning(None, "提示", f'第{i + 1}行第6和7列之一为空，请检查！', QMessageBox.Ok)
                flag = False
            else:
                jishu = self.tbw_pile.item(i, 5).text()
                ganchang = self.tbw_pile.item(i, 6).text()
                try:
                    if jishu.isdigit() and usedb.is_number(ganchang):
                        pass
                    else:
                        QMessageBox.warning(None, "提示", f'第{i + 1}行第6和7列之一，不是数字，请检查！', QMessageBox.Ok)
                        flag = False
                except Exception as e:
                    print(f"处理文件时出错：{e}")
                    flag = False
            if self.tbw_pile.item(i, 7) is None or self.tbw_pile.item(i, 7).text() == '':
                pass
            else:
                # 当mpa列不为空，则判断是否为数字。
                try:
                    mpa = self.tbw_pile.item(i, 7).text()
                    if usedb.is_number(mpa):
                        pass
                    else:
                        QMessageBox.warning(None, "提示", f'第{i + 1}行第8列，不是数字，请检查！', QMessageBox.Ok)
                        flag = False
                except Exception as e:
                    print(f"处理文件时出错：{e}")
        # 3、检测图片文件在窗口显示的文件夹下是否存在
        # 源文件路径
        pilepic_path_source = os.path.join(self.ledit_picpath.text(), self.ledit_pile.text()) + '.jpg'

        # 如果源文件存在，则显示信息
        if os.path.exists(pilepic_path_source):
            QMessageBox.information(None, '提示', f'{self.ledit_pile.text()}.jpg图片文件存在', QMessageBox.Ok)
        else:
            # 如果源文件不存在，则显示警告信息
            QMessageBox.warning(None, '警告', f'未找到{self.ledit_pile.text()}.jpg格式的图片文件', QMessageBox.Ok)
            flag = False
        # 显示最终数据检测结果
        if flag:
            QMessageBox.information(None, "提示", '数据检测通过', QMessageBox.Yes)
        else:
            QMessageBox.warning(None, "提示", '数据检测未通过，请检查！', QMessageBox.Ok | QMessageBox.Yes)
        return flag

    def get_state_score(self, state):
        STATE_SCORES = {
            "坚硬": 100,
            "坚硬-硬塑": 87.5,
            "硬塑": 75,
            "硬塑-可塑": 62.5,
            "可塑": 50,
            "可塑-软塑": 37.5,
            "软塑": 25,
            "软塑-流塑": 12.5,
            "流塑": 0
        }
        # 尝试从字典中获取分数，如果状态不存在，则抛出ValueError异常
        score = STATE_SCORES.get(state)
        if score is None:
            raise ValueError(f"未知的状态: {state}")
        return score

    def chazhi(self, x1, y1, x2, y2, x):
        """
        计算直线上某一点的纵坐标。

        参数:
        - x1, y1: 直线上的第一个点的坐标。
        - x2, y2: 直线上的第二个点的坐标。
        - x: 想要求得纵坐标的点的横坐标。

        返回值:
        - 计算得到的点的纵坐标。

        注意:
        - x1 和 x2 不应相等，否则将引发除零错误。
        """
        # Input validation
        for coordinate in [x1, y1, x2, y2, x]:
            if not isinstance(coordinate, (int, float)):
                raise ValueError("All coordinates must be numeric.")

        # Check for division by zero (vertical line)
        if x1 == x2:
            raise ZeroDivisionError("The line is vertical, x1 cannot equal x2.")
        return (x - x1) * (y2 - y1) / (x2 - x1) + y1

    def get_ganchang_discount(self, ganchang):
        if ganchang <= 3:
            return 1
        elif ganchang <= 6:
            return self.chazhi(3, 1, 6, 0.92, ganchang)
        elif ganchang <= 9:
            return self.chazhi(6, 0.92, 9, 0.86, ganchang)
        elif ganchang <= 12:
            return self.chazhi(9, 0.86, 12, 0.81, ganchang)
        elif ganchang <= 15:
            return self.chazhi(12, 0.81, 15, 0.77, ganchang)
        elif ganchang <= 18:
            return self.chazhi(12, 0.77, 18, 0.73, ganchang)
        elif ganchang <= 21:
            return self.chazhi(18, 0.73, 21, 0.7, ganchang)
        else:
            return 1000

    def get_linqi_discount(self, linqi):
        if linqi <= 28:
            return 1
        elif linqi <= 78:
            return 0.5 + (78 - linqi) * 0.01
        else:
            return 0.5

    def get_jishu_score(self, depth, jishu):
        if depth <= 5:
            if jishu < 5:
                score = 0
            elif jishu <= 15:
                score = self.chazhi(5, 50, 15, 75, jishu)
            elif jishu <= 20:
                score = self.chazhi(15, 75, 20, 100, jishu)
            else:
                score = 100
        elif depth > 5:
            if jishu < 4:
                score = 0
            elif jishu <= 10:
                score = self.chazhi(4, 50, 10, 75, jishu)
            elif jishu <= 15:
                score = self.chazhi(10, 75, 15, 100, jishu)
            else:
                score = 100
        else:
            score = 1000
        return score

    from typing import Union
    def get_mpa_score(self, depth, mpa: Union[str, float]):
        if isinstance(mpa, str):
            return 1000
        elif isinstance(mpa, float):
            if depth <= 5 and depth > 0:
                if mpa < 0.05:
                    score = 0
                elif mpa <= 0.2:
                    score = self.chazhi(0.05, 50, 0.2, 75, mpa)
                elif mpa <= 0.45:
                    score = self.chazhi(0.2, 75, 0.45, 100, mpa)
                else:
                    score = 100
            elif depth > 5:
                if mpa < 0.03:
                    score = 0
                elif mpa <= 0.2:
                    score = self.chazhi(0.03, 50, 0.2, 75, mpa)
                elif mpa <= 0.45:
                    score = self.chazhi(0.2, 75, 0.45, 100, mpa)
                else:
                    score = 100
            else:
                score = 1000
            return score

    def get_layer_score(self, state_score, jishu_score, mpa_score: Union[str, int, float]):
        if isinstance(mpa_score, str):
            return 0.2 * state_score + 0.8 * jishu_score
        else:
            return 0.15 * state_score + 0.7 * jishu_score + 0.15 * mpa_score

    def get_topbottom_score(self, begin_depth, end_depth, layersocres):
        depthtotal = end_depth - begin_depth
        topbottom_score = 0
        for i in range(0, len(layersocres)):
            if 1.5 * (i + 1) <= depthtotal:
                topbottom_score = 1.5 / depthtotal * layersocres[i]
            else:
                topbottom_score = (depthtotal - 1.5 * i) / depthtotal * layersocres[i]
        return topbottom_score

    def get_pile_grade(self, top_score, bottom_score):
        if bottom_score == 0:
            total_score = top_score
            if total_score < 75:
                return '不合格'
            elif total_score < 80:
                return '合格'
            elif total_score < 90:
                return '良'
            elif total_score <= 100:
                return '优'
            else:
                return '错误'
        else:
            total_score = (top_score + bottom_score) / 2
            if top_score >= 75 and bottom_score >= 60:
                if total_score < 67.5:
                    return '不合格'
                elif total_score < 80:
                    return '合格'
                elif total_score < 90:
                    return '良'
                elif total_score <= 100:
                    return '优'
                else:
                    return '错误'
            else:
                return '不合格'

    def insert_pile_info(self):
        # 数据检测、计算得分和向三个表中插入桩信息
        # 1、数据检测
        if self.checkdata() == False:
            return None
        # 2、计算得分
        ganchangs = []
        keys = [
            "序号", "桩号", "掺灰量", "施工时间", "检测时间", "龄期", "施工桩长", "实测桩长",
            "标贯个数", "室内试验", "层数", "层厚", "上部层厚", "下部层厚", "里程",
            "深度", "硬度状态", "状态得分", "标贯击数", "杆长折减击数", "龄期折减击数",
            "标贯得分", "强度(MPa)", "折算强度(MPa)", "强度得分", "每层得分", "上部得分",
            "下部得分", "综合得分", "综合评定"
        ]
        pile_data = dict.fromkeys(keys, None)
        pile_data['序号'] = self.num + 1
        pile_data['桩号'] = self.ledit_pile.text()
        pile_data['掺灰量'] = self.cbox_cement.currentText()
        pile_data['施工时间'] = self.dateed_begin.text()
        pile_data['检测时间'] = self.dateed_test.text()
        pile_data['龄期'] = self.get_days_between(self.dateed_begin.text(), self.dateed_test.text())
        pile_data['施工桩长'] = self.dsbox_begin.text()
        pile_data['实测桩长'] = self.dsbox_test.text()
        pile_data['标贯个数'] = self.tbw_pile.rowCount()
        pile_data["室内试验"] = 0
        pile_data['层数'] = self.tbw_pile.rowCount()
        pile_data['层厚'] = []
        pile_data['下部层厚'] = []
        pile_data['上部层厚'] = 0
        pile_data['下部层厚'] = 0
        pile_data['里程'] = self.cbox_mile.currentText()
        pile_data['深度'] = []
        pile_data['硬度状态'] = []
        pile_data['状态得分'] = []
        pile_data['标贯击数'] = []
        pile_data['杆长折减击数'] = []
        pile_data['龄期折减击数'] = []
        pile_data['标贯得分'] = []
        pile_data['强度(MPa)'] = []
        pile_data['折算强度(MPa)'] = []
        pile_data['强度得分'] = []
        pile_data['每层得分'] = []
        pile_data['上部得分'] = 0
        pile_data['下部得分'] = 0
        pile_data['综合得分'] = 0
        pile_data['综合评定'] = ''
        for i in range(1, pile_data['层数'] + 1):
            # 得到每层厚度
            if i < pile_data['层数']:
                pile_data['层厚'].append(1.5)
            else:
                pile_data['层厚'].append(float(pile_data['实测桩长']) - 1.5 * (i - 1))
        for i in range(0, pile_data['层数']):
            # 分别计算每层结果
            if self.tbw_pile.item(i, 7) is not None:
                pile_data['室内试验'] += 1
            depth = (1.5 * i + 1.5 * (i + 1)) / 2  # 击数和mpa深度简单的取层厚中间值
            depthtext = self.tbw_pile.item(i, 3).text()
            pile_data['深度'].append(depthtext)
            state = self.tbw_pile.cellWidget(i, 4).currentText()
            pile_data['硬度状态'].append(state)
            state_score = self.get_state_score(state)
            pile_data['状态得分'].append(round(state_score, 2))
            jishu = int(self.tbw_pile.item(i, 5).text())
            pile_data['标贯击数'].append(jishu)
            ganchang = float(self.tbw_pile.item(i, 6).text())
            pile_data['杆长折减击数'].append(round(self.get_ganchang_discount(ganchang) * jishu, 2))
            pile_data['龄期折减击数'].append(round(self.get_linqi_discount(pile_data['龄期']) * jishu, 2))
            jishu_score = self.get_jishu_score(depth, float(jishu)* self.get_ganchang_discount(
                ganchang) * self.get_linqi_discount(pile_data['龄期']))
            pile_data['标贯得分'].append(round(jishu_score, 2))
            if self.tbw_pile.item(i, 7) is not None and usedb.is_number(self.tbw_pile.item(i, 7).text()):
                mpa = float(self.tbw_pile.item(i, 7).text())
                pile_data['强度(MPa)'].append(mpa)
                mpa_discount = mpa * self.get_linqi_discount(pile_data['龄期'])
                pile_data['折算强度(MPa)'].append(round(mpa_discount, 2))
                mpa_score = self.get_mpa_score(depth, pile_data['折算强度(MPa)'][i])
                pile_data['强度得分'].append(round(mpa_score, 2))
                layer_score = self.get_layer_score(pile_data['状态得分'][i], pile_data['标贯得分'][i],
                                                   pile_data['强度得分'][i])
                pile_data['每层得分'].append(round(layer_score, 2))
            else:
                pile_data['强度(MPa)'].append('/')
                pile_data['折算强度(MPa)'].append('/')
                pile_data['强度得分'].append('/')
                layer_score = self.get_layer_score(pile_data['状态得分'][i], pile_data['标贯得分'][i],
                                                   pile_data['强度得分'][i])
                pile_data['每层得分'].append(round(layer_score, 2))
            if pile_data['上部层厚'] + pile_data['层厚'][i] <= 5:
                # 如果层号i的小计层厚小于5米，计算上层每层得分
                pile_data['上部层厚'] = pile_data['上部层厚'] + pile_data['层厚'][i]
                pile_data['上部得分'] = pile_data['上部得分'] + pile_data['层厚'][i] * pile_data['每层得分'][i]
            else:
                pile_data['下部层厚'] = pile_data['下部层厚'] + pile_data['层厚'][i]
                pile_data['下部得分'] = pile_data['下部得分'] + pile_data['层厚'][i] * pile_data['每层得分'][i]
            if i == pile_data['层数'] - 1:
                # 最后一个循环时，计算上部得分，下部得分、总得分和综合评定
                if pile_data['下部层厚'] == 0:
                    pile_data['上部得分'] = round(pile_data['上部得分'] / pile_data['上部层厚'], 2)
                    pile_data['下部得分'] = 0
                    pile_data['综合得分'] = pile_data['上部得分']
                    pile_data['综合评定'] = self.get_pile_grade(pile_data['上部得分'], pile_data['下部得分'])
                else:
                    pile_data['上部得分'] = round(pile_data['上部得分'] / pile_data['上部层厚'], 2)
                    pile_data['下部得分'] = round(pile_data['下部得分'] / pile_data['下部层厚'], 2)
                    pile_data['综合得分'] = round((pile_data['上部得分'] + pile_data['下部得分']) / 2, 2)
                    pile_data['综合评定'] = self.get_pile_grade(pile_data['上部得分'], pile_data['下部得分'])
        # 3、复制图片和向三个表中插入桩信息
        # self.dir_proj = os.path.join(usedb.cur_path, usedb.cur_proj)
        # self.csv_projinfo = os.path.join(self.dir_proj, f'{usedb.cur_proj}综合质量评分（表一）.csv')
        # self.csv_piletotal = os.path.join(self.dir_proj, f'{usedb.cur_proj}汇总信息表（表二）.csv')
        # self.csv_pile = os.path.join(self.dir_proj, f'{usedb.cur_proj}试验成果及得分表（表三）.csv')
        # 准备插入信息
        row_data1 = [[self.num + 1, pile_data['桩号'], pile_data['里程'], pile_data['施工桩长'], pile_data['实测桩长'],
                      pile_data['龄期'], pile_data['上部得分'], pile_data['下部得分'],
                      pile_data['综合得分'], pile_data['综合评定']]]
        row_data2 = [[self.num + 1, pile_data['桩号'], pile_data['里程'], pile_data['掺灰量'], pile_data['施工时间'],
                      pile_data['检测时间'], pile_data['龄期'], pile_data['施工桩长'], pile_data['实测桩长'],
                      pile_data['标贯个数'], pile_data['室内试验']]]
        data_to_write = []
        layer_thickness=0
        for i in range(0, pile_data['层数']):
            if layer_thickness+ pile_data['层厚'][i] <= 5:  # 上层输出
                layer_thickness += pile_data['层厚'][i]
                row_data3 = [
                    self.num + 1, pile_data['桩号'], pile_data['里程'], pile_data['龄期'],
                    pile_data['深度'][i], pile_data['硬度状态'][i],
                    pile_data['状态得分'][i], pile_data['标贯击数'][i], pile_data['杆长折减击数'][i],
                    pile_data['龄期折减击数'][i], pile_data['标贯得分'][i], pile_data['强度(MPa)'][i],
                    pile_data['折算强度(MPa)'][i], pile_data['强度得分'][i], pile_data['每层得分'][i]
                ]
                if i == 0:
                    # 上层第一层输出上层得分，综合得分，综合评定
                    row_extend = [pile_data['上部得分'], pile_data['综合得分'], pile_data['综合评定']]
                else:
                    # 上层其他层不输出上层得分，综合得分，综合评定
                    row_extend = ['/', '/', '/']
            else:  # 下层输出
                row_data3 = [
                    self.num + 1, pile_data['桩号'], pile_data['里程'], pile_data['龄期'],
                    pile_data['深度'][i], pile_data['硬度状态'][i],
                    pile_data['状态得分'][i], pile_data['标贯击数'][i], pile_data['杆长折减击数'][i],
                    pile_data['龄期折减击数'][i], pile_data['标贯得分'][i], pile_data['强度(MPa)'][i],
                    pile_data['折算强度(MPa)'][i], pile_data['强度得分'][i], pile_data['每层得分'][i]
                ]
                if i == 3:  # 下层第四层输出下层得分
                    row_extend = [pile_data['下部得分'], '/', '/']
                else:  # 下层其余层不输出上层得分，综合得分，综合评定
                    row_extend = ['/', '/', '/']
            # 写入每层数据
            row_data3.extend(row_extend)
            # 写入每根桩总数据
            data_to_write.append(row_data3)
        # 准备图片信息
        pilepic_path_source = os.path.join(self.ledit_picpath.text(), self.ledit_pile.text()) + '.jpg'
        pilepic_path_target = os.path.join(self.dir_images, self.ledit_pile.text()) + '.jpg'
        # 完成插入图片和插入数据
        if os.path.exists(pilepic_path_source):
            if pilepic_path_source == pilepic_path_target:
                # 如果源文件和目标文件相同，则不进行复制
                print(f"文件 {pilepic_path_source} 已存在且与目标路径相同，将进行替换。")
            try:
                shutil.copyfile(pilepic_path_source, pilepic_path_target)
                usedb.write_to_csv(self.csv_projinfo, row_data1)
                usedb.write_to_csv(self.csv_piletotal, row_data2)
                usedb.write_to_csv(self.csv_pile, data_to_write)
                print(f"文件 {pilepic_path_source} 已成功复制到 {pilepic_path_target}。")
                self.num += 1
            except Exception as e:
                print(f"复制文件时发生错误：{e}")
        else:
            # 如果源文件不存在，则显示警告信息
            QMessageBox.warning(None, 'warning', f'未找到.jpg格式的图片文件', QMessageBox.Ok)
